package _case

import (
	"fmt"
	"io"
	"log"
	"os"
)

// defer 声明一个延迟调用函数
// 函数可以是匿名函数，也可以是具名函数
// defer 执行顺序，先进后出，后进先出
func DeferCase1() {
	fmt.Println("程序开始执行DeferCase1")

	//
	defer func() {
		fmt.Println("调用了匿名函数1")
	}()

	defer f1()

	defer func() {
		fmt.Println("调用了匿名函数2")
	}()

	fmt.Println("程序DeferCase1执行结束")
}

// 参数预计数
func DeferCase2() {
	i := 1
	//传递的参数会进行预计算
	defer func(j int) {
		fmt.Println("defer j=", j)
	}(i + 1)

	defer func() {
		fmt.Println("defer i=", i)
	}()
	i = 99
	fmt.Println(i)
}

// 返回值
// defer 执行在return之后
func DeferCase3() {
	i, j := f2()
	fmt.Println(i, *j)
}

func ExceptionCase() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("异常处理 defer recover：", err)
		}
	}()

	fmt.Println("开始执行exception方法")
	panic("ExceptionCase抛出异常")
	fmt.Println("exception方法执行结束")
}

func FileReadCase() {
	//打开 README.md 文件，返回一个文件句柄 file 和一个可能的错误 err
	file, err := os.Open("README.md")
	if err != nil {
		//打印错误信息并终止程序
		log.Fatal(err)
	}
	//延迟执行 file.Close()，确保程序退出时释放文件句柄资源
	defer file.Close()

	//创建一个大小为 1024 字节的切片 buf，用作文件读取的缓冲区
	buf := make([]byte, 1024)
	for {
		//尝试从文件中读取最多 1024 字节（缓冲区大小），并将读取到的字节存入 buf
		n, err := file.Read(buf)
		//io.EOF 表示已到达文件末尾
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		if n == 0 {
			break
		}
		fmt.Println(string(buf[:n]))
	}
}

func f1() {
	fmt.Println("调用了具名函数f1")
}

var g = 100

func f2() (int, *int) {
	defer func() {
		g = 200
	}()
	return g, &g
}
